#include "../../ExEngine/math/matrix.h"

#include "../../ExEngine/physics/actor.h"
#include "../../ExEngine/physics/physics.h"
#include "../../ExEngine/math/quaternion.h"
#include "../../ExEngine/common/util.h"
#include "../../ExEngine/engine/engine.h"
#include "../../ExEngine/engine/object.h"
#include "../../ExEngine/engine/camera.h"
#include "../../ExEngine/render/d3d_mesh.h"
#include "../../ExEngine/render/d3d.h"
#include "../../ExEngine/sound/dsound.h"
#include "../../ExEngine/input/dinput.h"

#include "player.h"
#include "../game/core.h"

const float DURATION = 1.7525f;
const float MUZZLE = 0.005f;
const float OFFSHOOT = 0.5f;


#define WALK_SPEED 0.6f
#define RUN_SPEED 1.0f
#define STEER_SPEED 0.10f
#define AUTO_YAW_CORRECT 0.15f
#define CHASECAM_HOFFSET 3.75f
#define CHASECAM_VOFFSET 1.5f

/**********************************************************************
*
**********************************************************************/

CPlayer::CPlayer() : CObject()
{
	m_SteerUnarity = 1.0f;
	m_IsRunning = false;
	m_Angle = 0.0f;
	m_Speed = 0.0f;
	m_Driver = HUMAN;
}

HRESULT CPlayer::Create()
{	
	m_transform._M42 = 10;
	if(FAILED(CEngine::GetInstance()->GetRenderer()->CreateModel("Player.mdl", &m_pModel)))
	{
		Release();
		return E_FAIL;
	}

	CActor::ActorData data;
	data.initalTransform = m_transform;
	data.mass = 10.0f;
	data.friction = 0.0125f;
	data.restitution = 0.2f;
	data.maxForce = 200.0f;
	data.maxSlope = PI / 5.0f;

	if(FAILED(CEngine::GetInstance()->GetPhysics()->CreateCharacterActor("Player.phy", (CCharacterActor**) &m_pPhysics, data, this)))
	{
		Release();
		return E_FAIL;
	}

	//m_pPhysics->SetAngularDampening(100.0f);
	m_pModel->setRenderFlags(RENDER_DEFAULT);

	return S_OK;
}

HRESULT CPlayer::Release()
{	
	HRESULT result = S_OK;
	if(m_pModel)
	{
		m_pModel = NULL;
	}
	if(m_pPhysics)
	{
		CPhysics* pPhysics = CEngine::GetInstance()->GetPhysics();
		if(FAILED(pPhysics->ReleaseActor(m_pPhysics)))
			result = E_FAIL;
		m_pPhysics = NULL;
	}
	return result;
}

void CPlayer::OnLanding()
{
	m_jumpFlip.isDone = true;
	m_jumpFlip.angle = 0.0f;
}

void CPlayer::BeginJump()
{
	m_jumpFlip.isDone = false;
	m_jumpFlip.angle = 0.0f;
}

void CPlayer::BeginRunning()
{

}

void CPlayer::Running()
{
}

void CPlayer::EndRunning()
{
}

void CPlayer::Idle()
{
}

void CPlayer::setPosition(const Vector3f &position)
{
	m_transform = Matrix4f::identity();
	m_transform.SetTranslation(position); 
	if(m_pPhysics)
		m_pPhysics->SetTransform(m_transform);

	m_Angle = 0;
}
void CPlayer::UpdateTransform()
{
	CCharacterActor* pPhysicalActor = GetPhysicsCharacter();
	if(pPhysicalActor)
	{
		if(!m_jumpFlip.isDone)
		{
			if(m_jumpFlip.angle > TWOPI)
			{
				m_jumpFlip.isDone = true;
				m_jumpFlip.angle = 0.0f;
			}
			else
			{
				m_jumpFlip.angle += 0.25f;
			}
			m_transform = ((pPhysicalActor->GetTransform() * Matrix4f::rotateY(m_Angle)) * Matrix4f::rotateX(-m_jumpFlip.angle));

		}
		else
		{
			m_transform = pPhysicalActor->GetTransform() * Matrix4f::rotateY(m_Angle);
		}
		m_LastPosition = m_transform.Translation();
	}
}

void CPlayer::SetPointDriver(const Vector3f& target) {
	m_Driver = POINT;
	m_PointController = target;
}

void CPlayer::SetDirectionDriver(const Vector3f& target) {
	m_Driver = DIRECTION;
	m_PointController = target;
	Vector3f::normalize(&m_PointController);
}

void CPlayer::SetBezierDriver(const Bezier& target) {
	m_Driver = BEZIER;
	m_BezierController = target;
}

void CPlayer::SetHumanDriver() {
	m_Driver = HUMAN;
}

CPlayer::Driver CPlayer::GetDriver() {
	return m_Driver;
}

CCharacterActor* CPlayer::GetPhysicsCharacter()
{
	return (CCharacterActor*)m_pPhysics;
}

Vector3f CPlayer::CameraAnchor() {

	return m_CameraAnchor;

}
Vector3f CPlayer::CameraTarget() {

	return m_CameraTarget;

}

void CPlayer::RecoverDirection(const Vector3f& relativeTo) {
	
	Vector3f relativeToFlat = Vector3f(relativeTo.x, 0.0f, relativeTo.z);
	Vector3f flatForward = Vector3f(m_Forward.x, 0.0f, m_Forward.z);
	
	Vector3f::normalize(&relativeToFlat);
	Vector3f::normalize(&flatForward);

	m_Angle += (Vector3f::cross(&relativeToFlat, &flatForward).y > 0.0f) ? -AUTO_YAW_CORRECT : AUTO_YAW_CORRECT;
}
/*

//FIRST ATTEMPT

void CPlayer::UpdateHumanDriver(const float dt) {

	float walkSpeed = 0.0f;
	Vector3f changeDirection;
	{
		Vector3f playerPosition = m_transform.Translation();
		switch(Game::g_GamePlayMode) {

			case Game::SIDE_SCROLL: 
			{
				if(GetInput()->isKeyDown(DIK_LEFTARROW))
					changeDirection.x++;

				if(GetInput()->isKeyDown(DIK_RIGHTARROW))
					changeDirection.x--;

				if(GetInput()->isKeyDown(DIK_DOWNARROW))
					changeDirection.z++;

				if(GetInput()->isKeyDown(DIK_UPARROW))
					changeDirection.z--;
				
				changeDirection.y = 0;
				if(Vector3f::dot(&changeDirection) > 0.0f) {

					walkSpeed = GetMoveSpeed();
					m_Forward += changeDirection;
					Vector3f::normalize(&m_Forward);
				}
				else {
					walkSpeed = 0.0f;
				}
				m_Angle = atan2f(m_Forward.x, m_Forward.z);
				m_CameraAnchor = playerPosition + Vector3f(0.0f, 1.875f, -3.75f);
				m_CameraTarget = playerPosition;

			}break;

			case Game::CHASE:
			{
				m_CameraTarget = playerPosition;

				Vector3f backwardsVector;
				backwardsVector.x = playerPosition.x - m_CameraAnchor.x;
				backwardsVector.z = playerPosition.z - m_CameraAnchor.z;
				backwardsVector.y = 0.0f;

				Vector3f flatForward;
				flatForward.x = -m_Forward.x;
				flatForward.z = -m_Forward.z;
				flatForward.y = 0;

				Vector3f::normalize(&backwardsVector);
				Vector3f::normalize(&flatForward);

				if(GetInput()->isKeyDown(DIK_DOWNARROW)) {

					//If the player is pointing in the wrong direction, spin around before running
					//along the desired vector
					if(Vector3f::dot(&backwardsVector,&flatForward) > -0.975f) {

						m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y > 0.0f) ? AUTO_YAW_CORRECT : -AUTO_YAW_CORRECT;
						m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
						walkSpeed = 0.3f;
					}
					//Player pointing in similar direction to camera so move as normal
					else
					{
						walkSpeed = GetMoveSpeed();
						m_CameraAnchor = playerPosition + m_Forward * -CHASECAM_HOFFSET;
						m_CameraAnchor.y += CHASECAM_VOFFSET;
					}
				}

				if(GetInput()->isKeyDown(DIK_UPARROW)){

					if(Vector3f::dot(&backwardsVector,&flatForward) < 0.975f) {

						m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y < 0.0f) ? 0.15f : -0.15f;
						m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
						walkSpeed = 0.3f;
					}
					else
					{
						walkSpeed = GetMoveSpeed();
						m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET;
						m_CameraAnchor.y += CHASECAM_VOFFSET;
					}
				}

				//Enables the effects of steering even while running. Applies rotation ontop of
				//any previous rotation and recomputer the forward vector.
				if(GetInput()->isKeyDown(DIK_LEFTARROW)) {
					m_Angle -= 0.05f;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));	
				}

				if(GetInput()->isKeyDown(DIK_RIGHTARROW)){
					m_Angle += 0.05f;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
				}

				GetRenderer()->DrawLine(m_transform.Translation(),( m_transform.Translation() + m_Forward * 10), Color3f(0.0f,0.0f,1.0f));

			}break;
		}
	}

	m_Speed = walkSpeed;
}

//SECOND ATTEMPT

void CPlayer::UpdateHumanDriver(const float dt) {

	float walkSpeed = 0.0f;
	Vector3f changeDirection;

	Vector3f playerPosition = m_transform.Translation();
	switch(Game::g_GamePlayMode) {

		case Game::SIDE_SCROLL: 
		{
			if(GetInput()->isKeyDown(DIK_LEFTARROW))
				changeDirection.x++;

			if(GetInput()->isKeyDown(DIK_RIGHTARROW))
				changeDirection.x--;

			if(GetInput()->isKeyDown(DIK_DOWNARROW))
				changeDirection.z++;

			if(GetInput()->isKeyDown(DIK_UPARROW))
				changeDirection.z--;
			
			changeDirection.y = 0;
			if(Vector3f::dot(&changeDirection) > 0.0f) {

				walkSpeed = GetMoveSpeed();
				m_Forward += changeDirection;
				Vector3f::normalize(&m_Forward);
			}
			else {
				walkSpeed = 0.0f;
			}
			m_Angle = atan2f(m_Forward.x, m_Forward.z);
			m_CameraAnchor = playerPosition + Vector3f(0.0f, 1.875f, -3.75f);
			m_CameraTarget = playerPosition;

		}break;

		case Game::CHASE:
		{
			m_CameraTarget = playerPosition;

			Vector3f backwardsVector;
			backwardsVector.x = playerPosition.x - m_CameraAnchor.x;
			backwardsVector.z = playerPosition.z - m_CameraAnchor.z;
			backwardsVector.y = 0.0f;

			Vector3f flatForward;
			flatForward.x = -m_Forward.x;
			flatForward.z = -m_Forward.z;
			flatForward.y = 0;

			Vector3f::normalize(&backwardsVector);
			Vector3f::normalize(&flatForward);

			if(GetInput()->isKeyPressed(DIK_LEFTARROW) || GetInput()->isKeyPressed(DIK_RIGHTARROW) || 
				GetInput()->isKeyPressed(DIK_UPARROW)  || GetInput()->isKeyPressed(DIK_DOWNARROW))
				m_SteerUnarity = (Vector3f::dot(&flatForward, &backwardsVector) > 0.0) ? 1.0f : -1.0f;
			//CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::DEFAULT_FACE, "Player facing camera %f",steerUnarity);
			

			if(GetInput()->isKeyDown(DIK_DOWNARROW)) {

				//If the player is pointing in the wrong direction, spin around before running
				//along the desired vector
				if(Vector3f::dot(&backwardsVector,&flatForward) > -0.975f) {

					m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y > 0.0f) ? AUTO_YAW_CORRECT : -AUTO_YAW_CORRECT;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
					walkSpeed = WALK_SPEED * 0.25f;
				}
				//Player pointing in similar direction to camera so move as normal
				else
				{
					walkSpeed = GetMoveSpeed();
					m_CameraAnchor = playerPosition + m_Forward * -CHASECAM_HOFFSET * 1.5f;
					m_CameraAnchor.y += CHASECAM_VOFFSET;
				}
			}
			
			//CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::DEFAULT_FACE, "Cam playr dist: %f", Vector3f::distance(&Game::g_Player->getPosition(), &CEngine::GetInstance()->GetCamera()->getPosition()));

			if(GetInput()->isKeyDown(DIK_UPARROW)){

				
				if(Vector3f::dot(&backwardsVector,&flatForward) < 0.975f && false) {

					m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y < 0.0f) ? AUTO_YAW_CORRECT : -AUTO_YAW_CORRECT;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
					walkSpeed = WALK_SPEED * 0.25f;
				}
				else
				{
					walkSpeed = GetMoveSpeed();
					const float distCameraPlayer = Vector3f::distance(&Game::g_Player->getPosition(), &CEngine::GetInstance()->GetCamera()->getPosition());
					if(distCameraPlayer > (CHASECAM_HOFFSET + CHASECAM_VOFFSET)) {
						m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET;
						m_CameraAnchor.y += CHASECAM_VOFFSET;
					}
				}
			}

			//Enables the effects of steering even while running. Applies rotation ontop of
			//any previous rotation and recomputer the forward vector.
			if(GetInput()->isKeyDown(DIK_LEFTARROW)) {
				m_Angle -= STEER_SPEED * m_SteerUnarity;
				m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));	
			}

			if(GetInput()->isKeyDown(DIK_RIGHTARROW)){
				m_Angle += STEER_SPEED * m_SteerUnarity;
				m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
			}

			GetRenderer()->DrawLine(m_transform.Translation(),( m_transform.Translation() + m_Forward * 10), Color3f(0.0f,0.0f,1.0f));

		}break;
	}

	m_Speed = walkSpeed;
}
*/
/*
//////////////////// THIRD ATTEMPT
void CPlayer::UpdateHumanDriver(const float dt) {

	float walkSpeed = 0.0f;
	Vector3f changeDirection;

	Vector3f playerPosition = m_transform.Translation();
	switch(Game::g_GamePlayMode) {

		case Game::SIDE_SCROLL: 
		{
			if(GetInput()->isKeyDown(DIK_A))
				changeDirection.x++;

			if(GetInput()->isKeyDown(DIK_D))
				changeDirection.x--;

			if(GetInput()->isKeyDown(DIK_S))
				changeDirection.z++;

			if(GetInput()->isKeyDown(DIK_W))
				changeDirection.z--;
			
			changeDirection.y = 0;
			if(Vector3f::dot(&changeDirection) > 0.0f) {

				walkSpeed = GetMoveSpeed();
				m_Forward += changeDirection;
				Vector3f::normalize(&m_Forward);
			}
			else {
				walkSpeed = 0.0f;
			}
			m_Angle = atan2f(m_Forward.x, m_Forward.z);
			m_CameraAnchor = playerPosition + Vector3f(0.0f, 1.875f, -3.75f);
			m_CameraTarget = playerPosition;

		}break;

		case Game::CHASE:
		{
			m_CameraTarget = playerPosition;

			Vector3f backwardsVector;
			backwardsVector.x = playerPosition.x - m_CameraAnchor.x;
			backwardsVector.z = playerPosition.z - m_CameraAnchor.z;
			backwardsVector.y = 0.0f;

			Vector3f flatForward;
			flatForward.x = -m_Forward.x;
			flatForward.z = -m_Forward.z;
			flatForward.y = 0;

			Vector3f::normalize(&backwardsVector);
			Vector3f::normalize(&flatForward);

			
			if(GetInput()->isKeyDown(DIK_S)) {

					walkSpeed = -GetMoveSpeed();
					m_CameraAnchor = playerPosition + m_Forward * -CHASECAM_HOFFSET * 1.5f;
					m_CameraAnchor.y += CHASECAM_VOFFSET;
				
			}

			if(GetInput()->isKeyDown(DIK_W)){

				
				if(Vector3f::dot(&backwardsVector,&flatForward) < 0.975f && false) {

					m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y < 0.0f) ? AUTO_YAW_CORRECT : -AUTO_YAW_CORRECT;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
					walkSpeed = WALK_SPEED * 0.25f;
				}
				else
				{
					walkSpeed = GetMoveSpeed();
					const float distCameraPlayer = Vector3f::distance(&Game::g_Player->getPosition(), &CEngine::GetInstance()->GetCamera()->getPosition());
					if(distCameraPlayer > (CHASECAM_HOFFSET + CHASECAM_VOFFSET)) {
						m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET;
						m_CameraAnchor.y += CHASECAM_VOFFSET;
					}
				}
			}

			Vector2i mouseMove = GetInput()->getMouseDelta();
			Vector2f mouseDelta = Vector2f(mouseMove.x * 0.01f,mouseMove.y * 0.0001f);

			m_Angle += mouseDelta.x;
			m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET + Vector3f(0, CHASECAM_VOFFSET, 0);

			if(mouseMove.y > 0.0f) {
				if(m_CameraAnchor.y - playerPosition.y < CHASECAM_VOFFSET * 2)
					m_CameraAnchor.y += 0.1f;
				else
					m_CameraAnchor.y = playerPosition.y + CHASECAM_VOFFSET * 2;
			
			} else if(mouseMove.y < 0.0f) {
				if(playerPosition.y - m_CameraAnchor.y < CHASECAM_VOFFSET * 2)
					m_CameraAnchor.y -= 0.1f;
				else
					m_CameraAnchor.y = playerPosition.y - CHASECAM_VOFFSET * 2;
			}

			m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));	


			GetRenderer()->DrawLine(m_transform.Translation(),( m_transform.Translation() + m_Forward * 10), Color3f(0.0f,0.0f,1.0f));

		}break;
	}

	m_Speed = walkSpeed;
}
*/
float CPlayer::GetInputSteer() {

	float magnitude = GetInput()->getMouseDelta().x;

	if(GetInput()->isKeyDown(DIK_D))
		magnitude ++;
	if(GetInput()->isKeyDown(DIK_A))
		magnitude --;

	return magnitude;
}

float CPlayer::GetWalkMagnitude() {

	return 0;
}

void CPlayer::UpdateHumanDriver(const float dt) {

	float walkSpeed = 0.0f;
	Vector3f changeDirection;

	Vector3f playerPosition = m_transform.Translation();
	switch(Game::g_GamePlayMode) {

		case Game::SIDE_SCROLL: 
		{
			if(GetInput()->isKeyDown(DIK_W)) {
				walkSpeed = GetMoveSpeed();
				changeDirection.z --;
			}
			if(GetInput()->isKeyDown(DIK_S)) {
				walkSpeed = GetMoveSpeed();
				changeDirection.z ++;
			}
			if(GetInput()->isKeyDown(DIK_A)) {
				walkSpeed = GetMoveSpeed();
				changeDirection.x ++;
			}
			if(GetInput()->isKeyDown(DIK_D)) {
				walkSpeed = GetMoveSpeed();
				changeDirection.x --;
			}
			m_Forward += changeDirection;
			Vector3f::normalize(&m_Forward);

			m_Angle = atan2f(m_Forward.x, m_Forward.z);
			m_CameraAnchor = playerPosition + Vector3f(0.0f, 1.875f, -3.75f);
			m_CameraTarget = playerPosition;
			


			/*
			//MOUSE CONTROL SCROLL STEER
			int mouseMoveX = GetInput()->getMouseDelta().x;
#define MOVE_AMOUNT 20
			if(mouseMoveX < -MOVE_AMOUNT)
				changeDirection.x = 1;
			else if(mouseMoveX > MOVE_AMOUNT)
				changeDirection.x = -1;

			int mouseMoveZ = GetInput()->getMouseDelta().y;
			if(mouseMoveZ < -MOVE_AMOUNT)
				changeDirection.z = -1;
			else if(mouseMoveZ > MOVE_AMOUNT)
				changeDirection.z = 1;

			if(GetInput()->isKeyDown(DIK_W))
				walkSpeed = GetMoveSpeed();
			if(GetInput()->isKeyDown(DIK_S))
				walkSpeed = -GetMoveSpeed();

			m_Forward += changeDirection;
			Vector3f::normalize(&m_Forward);

			m_Angle = atan2f(m_Forward.x, m_Forward.z);
			m_CameraAnchor = playerPosition + Vector3f(0.0f, 1.875f, -3.75f);
			m_CameraTarget = playerPosition;*/

		}break;

		case Game::CHASE:
		{
			m_CameraTarget = playerPosition;

			Vector3f backwardsVector;
			backwardsVector.x = playerPosition.x - m_CameraAnchor.x;
			backwardsVector.z = playerPosition.z - m_CameraAnchor.z;
			backwardsVector.y = 0.0f;

			Vector3f flatForward;
			flatForward.x = -m_Forward.x;
			flatForward.z = -m_Forward.z;
			flatForward.y = 0;

			Vector3f::normalize(&backwardsVector);
			Vector3f::normalize(&flatForward);

			
			if(GetInput()->isKeyDown(DIK_S)) {

					walkSpeed = -GetMoveSpeed();
					m_CameraAnchor = playerPosition + m_Forward * -CHASECAM_HOFFSET * 1.5f;
					m_CameraAnchor.y += CHASECAM_VOFFSET;
				
			}

			if(GetInput()->isKeyDown(DIK_W)){

				
				if(Vector3f::dot(&backwardsVector,&flatForward) < 0.975f && false) {

					m_Angle += (Vector3f::cross(&backwardsVector, &flatForward).y < 0.0f) ? AUTO_YAW_CORRECT : -AUTO_YAW_CORRECT;
					m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));
					walkSpeed = WALK_SPEED * 0.25f;
				}
				else
				{
					walkSpeed = GetMoveSpeed();
					const float distCameraPlayer = Vector3f::distance(&Game::g_Player->getPosition(), &CEngine::GetInstance()->GetCamera()->getPosition());
					if(distCameraPlayer > (CHASECAM_HOFFSET + CHASECAM_VOFFSET)) {
						m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET;
						m_CameraAnchor.y += CHASECAM_VOFFSET;
					}
				}
			}

			Vector2i mouseMove = GetInput()->getMouseDelta();
			Vector2f mouseDelta = Vector2f(mouseMove.x * 0.01f,mouseMove.y * 0.0001f);

			m_Angle += mouseDelta.x;
			m_CameraAnchor = playerPosition + m_Forward * CHASECAM_HOFFSET + Vector3f(0, CHASECAM_VOFFSET, 0);

			if(mouseMove.y > 0.0f) {
				if(m_CameraAnchor.y - playerPosition.y < CHASECAM_VOFFSET * 2)
					m_CameraAnchor.y += 0.1f;
				else
					m_CameraAnchor.y = playerPosition.y + CHASECAM_VOFFSET * 2;
			
			} else if(mouseMove.y < 0.0f) {
				if(playerPosition.y - m_CameraAnchor.y < CHASECAM_VOFFSET * 2)
					m_CameraAnchor.y -= 0.1f;
				else
					m_CameraAnchor.y = playerPosition.y - CHASECAM_VOFFSET * 2;
			}

			m_Forward = Vector3f(sinf(m_Angle), 0.0f, cosf(m_Angle));	


			GetRenderer()->DrawLine(m_transform.Translation(),( m_transform.Translation() + m_Forward * 10), Color3f(0.0f,0.0f,1.0f));

		}break;
	}

	m_Speed = walkSpeed;
}

void CPlayer::UpdatePointDriver(const float dt) {
	
	
	Vector3f playerPosition = m_transform.Translation();

	Vector3f toPointController = playerPosition - m_PointController;
	toPointController.y = 0.0f;


	const float distanceToTarget = Vector3f::length(&toPointController);

	Vector3f::normalize(&toPointController);

	CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::DEFAULT_FACE, "Dist to tgt: %f", distanceToTarget);
	if(distanceToTarget > 0.05f)
	{
		m_Forward = toPointController;
		m_Angle = atan2f(m_Forward.x, m_Forward.z);
		m_Speed = WALK_SPEED;
	}
}

void CPlayer::UpdateDirectionDriver(const float dt) {
	
	//Reinterpert m_PointController as the direction
	
	Vector3f toDirection = (m_Forward - m_PointController );
	if(Vector3f::length(&toDirection) > 0.25f)
		Vector3f::normalize(&toDirection);

	m_Forward += (toDirection * 0.25f);
	Vector3f::normalize(&m_Forward);
	m_Angle = atan2f(m_Forward.x, m_Forward.z);
	m_Speed = WALK_SPEED;
}

void CPlayer::UpdateBezierDriver(const float dt) {
	CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::ERROR_FACE, "BezierDriver not yet implemented");
}


float CPlayer::GetMoveSpeed() {
	return GetInput()->isKeyDown(DIK_LSHIFT) ? RUN_SPEED : WALK_SPEED;
}
void CPlayer::Update(const float dt)
{	
	CCharacterActor* pPhysicalActor = GetPhysicsCharacter();
	CCharacterActor::CharacterState physicsCharacterState = pPhysicalActor->GetState();
m_Speed = 0.0f;
	m_velocity = pPhysicalActor->GetLinearVelocity();
	CEngine::GetInstance()->GetRenderer()->WriteLine(ScreenText::ERROR_FACE, "%f,%f,%f", m_Forward.x, m_Forward.y,m_Forward.z);

	switch(m_Driver) { 
		case HUMAN: 
			UpdateHumanDriver(dt);
			break;
		case BEZIER:
			UpdateBezierDriver(dt);
			break;
		case POINT:
			UpdatePointDriver(dt);
			break;
		case DIRECTION:
			UpdateDirectionDriver(dt);
			break;
	};
	
	/************************************************************
	* Event detection and firing
	*/
	{

		if(physicsCharacterState == CCharacterActor::ON_GROUND && (m_LastPhysicsState == CCharacterActor::JUMPING || m_LastPhysicsState == CCharacterActor::IN_AIR))
			CallEvent(&CPlayer::OnLanding);

		if(physicsCharacterState == CCharacterActor::IN_AIR || physicsCharacterState == CCharacterActor::JUMPING)
		{
			pPhysicalActor->ApplyMovement(m_Speed, 0.0f, m_Forward, false);
		}
		else
		{
			if(GetInput()->isKeyPressed(DIK_SPACE))
			{
				CallEvent(&CPlayer::BeginJump);
				pPhysicalActor->ApplyMovement(m_Speed, 0.0f, m_Forward, true);
			}
			else
			{
				pPhysicalActor->ApplyMovement(m_Speed, 0.0f, m_Forward, false);
			}
		}

		if(m_Speed != 0.0f)
		{
			CallEvent(m_IsRunning ? &CPlayer::Running : &CPlayer::BeginRunning);
			m_IsRunning = true;
		}
		else
		{
			if(m_IsRunning)
			{
				CallEvent(&CPlayer::EndRunning);
				m_IsRunning = false;
			}
			else
			{
				CallEvent(&CPlayer::Idle);
			}
		}
	}

	UpdateTransform();
	m_LastPhysicsState = physicsCharacterState;
}

void CPlayer::Draw()
{	
	if(m_pModel)
	{

		GetRenderer()->DrawPoint(m_transform.Translation(), 2.0f);
		GetRenderer()->DrawPoint(m_transform.Translation() + m_transform.Foward());
		m_pModel->Draw(m_transform,m_velocity);

	}

}